﻿using System;
using System.Collections.Generic;
using Internal.Runtime.Services.Battle.Behaviour;
using Internal.Runtime.Services.Battle.Entity;
using KuiHuaBaoDian.Services.Lockstep;
using Runtime.Services.Battle;
using Runtime.Services.Battle.Behaviour;
using Runtime.Services.Battle.Entity;
using Runtime.Services.Battle.StateMachine;
using UnityEngine;
using UnityEngine.Pool;

namespace Runtime.Services.Battle.Entity {

    /// <summary>
    /// 战斗实体
    /// </summary>
    public interface IDFR_BattleEntityBase : ILockstepEntity, IDFR_Entity {
    }

    public abstract class DFR_BattleEntityBase : DFR_PoolEntity, IDFR_BattleEntityBase, IDFR_BattleEntityBaseInternal, IDFR_BattleEntityStateSpeedGetter {

        private event IDFR_BattleEntityBaseInternal.EntityDelegate Attached;
        event IDFR_BattleEntityBaseInternal.EntityDelegate IDFR_BattleEntityBaseInternal.Attached {
            add => Attached += value;
            remove => Attached -= value;
        }

        private event IDFR_BattleEntityBaseInternal.EntityDelegate Detached;
        event IDFR_BattleEntityBaseInternal.EntityDelegate IDFR_BattleEntityBaseInternal.Detached {
            add => Detached += value;
            remove => Detached -= value;
        }

        public DFR_BattleEntityHandle Handle { get; private set; }

        protected GameObject Container { get; private set; }

        protected Transform Transformer { get; private set; }

        protected Transform ModelContainer { get; private set; }

        protected List<IDFR_BattleBehaviourInfo> BehaviourInfoList { get; private set; }

        protected IDFR_BattleEntityAssetVehicle StateVehicle { get; private set; }

        protected IDFR_BattleEntityAssetVehicle SFXVehicle { get; private set; }

        float IDFR_BattleEntityStateSpeedGetter.GetValue(DFR_BattleEntityState state) => GetStateSpeed(state);

        protected abstract float GetStateSpeed(DFR_BattleEntityState state);

        protected abstract void DoLogicFrame(int frameIndex);
        void ILockstepEntity.DoLogicFrame(int frameIndex) {
            if (IsDisposed) {
                return;
            }
            DoLogicFrame(frameIndex);
        }

        protected abstract void EndUpdate(float timeScale);

        protected abstract void DoExecute(IDFR_BattleBehaviourInfo behaviourInfo);

        protected abstract void DoUpdate();

        void ILockstepEntity.DoUpdate(int frameIndex, int syncedFrameCount, float deltaTime, float timeScale) {
            if (IsDisposed) {
                return;
            }

            for (var i = 0; i < BehaviourInfoList.Count; ++i) {
                var behaviourInfo = BehaviourInfoList[i];
                if ((behaviourInfo as IDFR_BattleBehaviourInfoInternal).FrameIndex > LockstepService.Instance.AccumulatedFrame) {
                    break;
                }
                DoExecute(behaviourInfo);
                BehaviourInfoList.RemoveAt(i--);
            }

            DoUpdate();
            EndUpdate(timeScale);
        }

        protected virtual void OnAttached(int frameIndex) { }
        void ILockstepEntity.OnAttached(int frameIndex) {
            Attached?.Invoke();
            OnAttached(frameIndex);
        }

        protected virtual void OnDetached() { }
        void ILockstepEntity.OnDetached() {
            OnDetached();
            Detached?.Invoke();
        }

        void IDFR_BattleEntityBaseInternal.Initialize(DFR_BattleEntityHandle handle, GameObject container, Transform transformer, Transform modelContainer, IDFR_BattleEntityAssetVehicle stateVehicle, IDFR_BattleEntityAssetVehicle sfxVehicle) {
            Handle = handle;
            Container = container;
            Transformer = transformer;
            ModelContainer = modelContainer;
            StateVehicle = stateVehicle;
            SFXVehicle = sfxVehicle;
        }

        protected override void Allocate() {
            BehaviourInfoList = ListPool<IDFR_BattleBehaviourInfo>.Get();
        }

        protected override void Release() {
            Attached = null;
            Detached = null;
            Container = null;
            Transformer = null;
            ModelContainer = null;
            StateVehicle = null;
            SFXVehicle = null;
            Handle = DFR_BattleEntityHandle.Empty;
            if (BehaviourInfoList != null) {
                ListPool<IDFR_BattleBehaviourInfo>.Release(BehaviourInfoList);
                BehaviourInfoList = null;
            }
        }
    }
}

namespace Internal.Runtime.Services.Battle.Entity {

    public interface IDFR_BattleEntityBaseInternal : IDFR_BattleEntityBase, IDisposable {

        public delegate void EntityDelegate();

        event EntityDelegate Attached;

        event EntityDelegate Detached;

        void Initialize(DFR_BattleEntityHandle handle, GameObject container, Transform transformer, Transform modelContainer, IDFR_BattleEntityAssetVehicle stateVehicle, IDFR_BattleEntityAssetVehicle sfxVehicle);
    }
}
